% The class: the leet one
\documentclass[a4paper]{memoir}
\pdfoutput = 1
\usepackage{listings}
\usepackage{graphicx}
\lstset{language=C}

% DISCLAIMER
% Questo file e` stato prodotto a puro scopo personale e lo condivido con il solo
% scopo di condividerlo: in nessun modo l'intento di questo file e` quello di proporre
% o imporre una struttura ad un documento di tesi
%
% In nessun modo sono responsabile dell'(ab)uso di questo file o di altri file che
% ne possono derivare
%
% Federico (fmaggi@elet.polimi.it)

% GUIDELINE
% - Consiglio di usare PDFLaTeX e di conseguenza figure in .pdf
% - Per vari motivi separo il frontespizio dal resto della tesi: compilatelo a parte
%   ed includetelo togliendo il commento al comando di seguito che include il PDF frontespizio/main
% - Non servono altri package a meno di scopi particolari: ho incluso tutto il necessario
%   in preamble.tex
% - Mi riferisco sempre alla ``nuova'' filosofia di usare LaTeX quindi per problemi, errori o
%   situazioni di panico, perfavore rifatevi a questi due riferimenti e a nient'altro:
%      - memoir: http://www.ctan.org/tex-archive/macros/latex/contrib/memoir/memman.pdf
%      - cose da non fare: http://www.ctan.org/tex-archive/info/l2tabu/italian/l2tabuit.pdf
% - Se vi state chiedendo come mai il margine piu` esterno e` maggiore di quello interno allora non
%   avete letto `memman.pdf' :-D
% - Per COMPILARE: 1) latex, 2) bibtex, 3) latex, 4) latex
% - Se ancora non lo usate consiglio l'ambiente AUCTeX+RefTeX sotto Emacs

% Dedicated settings
\input{preamble}

\begin{document}
\pagestyle{empty}
\includepdf[pages=1]{frontespizio/main}

\frontmatter
\pagestyle{plain}

% Dedication
\begin{epigraphs}
  \qitem{
    Dedicato a...
  }{\small Matteo Michelini}
\end{epigraphs}

% Acknowkedgements
\chapter*{Ringraziamenti}
Ringrazio....

% Lists
\clearpage
\tableofcontents
\clearpage
\listoffigures
\clearpage
\listoftables

% Main text
\mainmatter
\pagestyle{Ruled}

% --------------------
\chapter{Introduzione}
%Da scrivere l'ultimo giorno

\chapter{Auditing}
In questo capitolo vengono presentate le caratteristiche dei sistemi di Auditing
nei principali Sistemi Operativi. Dopo una breve introduzione alle funzionalit\'a dei 
Sistemi Opertivi si affrontano le ragioni per le quali \'e necessario implementare un sistema
di Auditing e le implementazioni di questo nei Sistemi UNIX e Unix-like quali FreeBSD e Linux. 
Viene descritto il formato OpenBSM, considerato lo standard de facto nel logging degli 
eventi del Sistema Operativo e come questo soddisfi i criteri elencati nel CAPP facente capo 
alle norme C2 del TCSEC (Trusted Computer System Evaluation Criteria) stilato dal Department 
of Defense. I riferimenti bibliografici utilizzati spaziano dagli articoli sul 
Common Criteria~\cite{ref6} a quelli sul formato OpenBSM~\cite{ref12} per arrivare ai 
libri sulle strutture interne dei kernel UNIX~\cite{ref11}, FreeBSD~\cite{ref16} e 
Linux~\cite{ref7}~\cite{ref8}.

\section{Sistemi Operativi}
In questa sezione vengono illustrate le componenti di base di un Sistema Operativo. Questi concetti
verranno utilizzati per discutere l'implementazione del sistema di Auditing nei kernel UNIX e 
Unix-like.\\

Il Sistema Operativo \'e l'insieme di routine e strutture dati responsabili del controllo e della 
gestione dei componenti hardware che costituiscono un computer e dei programmi che su di esso girano. 
Il sistema operativo mette anche a disposizione dei programmi un set di API, cio\'e una interfaccia 
software per accedere alle risorse hardware (dischi, memoria, I/O in generale) del sistema.\\
Un generico Sistema Operativo \'e composto dalle seguenti parti:
\begin{itemize}
\item \textbf{kernel}: un gruppo di funzioni fondamentali, strettamente interconnesse fra loro e con 
l'hardware, che vengono eseguite con il privilegio massimo disponibile sulla macchina; il kernel 
fornisce le funzionalit\'a di base per tutte le altre componenti del sistema operativo che assolvono 
le loro funzioni servendosi di esso. A seconda che il kernel sia monolitico, microkernel, exokernel, modulare
altre componenti possono rientrare a far parte di questo quali: il gestore di filesystem, lo scheduler e
il gestore di memoria virtuale
\item \textbf{interfaccia utente}: shell o GUI\footnote[1]{GUI: Graphical User Interface} che permette
agli esseri umani di interagire con la macchina.
\end{itemize}

Di fondamentale importanza risulta essere la divisione della memoria su sistemi Unix/Unix-like.
\begin{itemize}
\item \textbf{kernel space}: \'e la zona di memoria dove viene eseguito il kernel con i privilegi massimi
disponibili sulla macchina
\item \textbf{user space}: \'e la zona di memoria dove vengono eseguiti i processi dell'utente (tutto ci\'o
che non sia appartenente al kernel)
\end{itemize}
I processi in \textit{user space} possono accedere a \textit{kernel space} solo tramite le \textbf{system call}.
Le \textit{system call} possono essere chiamate da un processo attivo per richiedere dei servizi al kernel come
ad esempio operazioni di input/output o creazione di altri processi. Un processo viene definito attivo nel momento in 
cui viene eseguito dalla CPU\footnote[2]{CPU: Central Processing Unit} mentre, un processo viene definito in attesa,
quando sta aspettando il suo turno per essere eseguito. Il compito di dedicare timeslices e priorit\'a ai processi, 
di eseguirli e sospenderli \'e affidato allo scheduler.

\section{Auditing a Kernel Space}
In questa sezione vengono spiegate le ragioni per le quali il sistema di auditing viene sviluppato a kernel space al
fine di rispettare gli standard di sicurezza esposti nel CC~\cite{ref17}. 
\\
\subsection{Cos'\'e l'Auditing}
Le system call sono l'unico strumento messo a disposizione ai processi in user space per accedere alla zona di memoria
dove risiede il kernel e dove girano i processi con privilegi massimi. Risulta pertanto necessario controllare le
chiamate e l'esecuzione delle system call in modo da rilevare eventuali utilizzi impropri delle medesime al fine di
penetrare nel sistema da parte di utenti malintenzionati.
Per garantire l'integrit\'a di un sistema \'e quindi importante verificare il corretto uso delle system call.

\subsection{Perch\'e lavorare a Kernel Space}
Il kernel \'e il cuore del Sistema Operativo se viene rilevato un bug a kernel space significa che \'e compromessa
l'intera stabilit\'a del sistema. Per questa ragione normalmente non vengono aggiunte funzionalit\'a al kernel se non
strettamente necessario. \'E preferibile integrare nuove funzionalit\'a a user space per le seguenti ragioni:
\begin{itemize}
\item I sistemi Unix-like generalmente sono POSIX pertanto viene garantita un'interfaccia standard per le applicazioni
in user space e risulta semplice utilizzarla per implementare novo software
\item Le API all'interno del kernel vengono rivisitate costantemente pertanto risulta oneroso mantenere il codice aggiornato
e compatibile con le nuove release del kernel
\item Il codice a kernel space non e` portabile, funziona solo con quel kernel e in alcuni casi solo con quella particolare
versione del kernel
\item Il codice a user space e` portabile se scritto con criterio
\item La documentazione delle API a kernel space spesso e` obsoleta o del tutto inesistente
\item La fase di testing e debugging a user space risulta essere pi\'u semplice
\end{itemize}
Nonostante queste controindicazioni risulta essenziale sviluppare un sistema di Auditing a kernel space per soddisfare il 
CAPP.

\subsection{Cos'\'e il CAPP}
CAPP \'e un acronimo che sta per Controlled Access Protection Profile e fa parte del set di documenti
del Common Criteria~\cite{ref17} che stabilisce le linee guida per sviluppare e valutare un prodotto informatico sotto il profilo 
della sicurezza. Il Common Criteria fa riferimento all'implementazione del prodotto e non all'utilizzo di questi. 
Il Common Criteria si suddivide in diversi \textit{Profili di Protezione}; ogni Profilo di Protezione \'e costituito da 
un insieme di requisiti di sicurezza che il sistema deve soddisfare. Il CAPP fa riferimento al Controllo ad Accesso 
Discrezionale (DAC) e richiede un l'implementazione di un sistema di auditing con le seguenti caratteristiche fondamentali:
\begin{itemize}
\item controllo di interazione tra diversi oggetti
\item controllo di eventi di login/logout
\item controllo sugli stessi eventi di auditing
\end{itemize}
Il CAPP corrisponde alla classe C2 del TCSEC~\cite{ref6}.

\subsection{Cos'\'e il TCSEC}
Il TCSEC \'e un acronimo che sta per Trusted Computer System Evaluation Criteria ed \'e` un documento sviluppato dal
Department of Defense circa i gradi di sicurezza adottabili e quindi certificabili su un sistema informatico. 
Ha tre obiettivi principali:

\begin{itemize}
\item Esporre agli utenti quali metodi sono utilizzabili su un sistema informatico al fine di garantire determinati
standard di sicurezza
\item Esporre ai fornitori di impianti informatici le metodologie per implementare i vari gradi di sicurezza a seconda
della sensibilit\'a delle informazioni che questi sistemi devono trattare
\item Fornire una base per specificare requisiti di sicurezza
\end{itemize}

I Gradi di sicurezza esposti sono quattro:

\begin{itemize}
\item \textbf{Divisione D}: Protezione Minima, riservata a quei sistemi che sono stati valutati ma che non rientrano in
sistemi di sicurezza superiori
\item \textbf{Divisione C}: Protezione Discrezionale, sistemi che integrano funzionalit\'a di Auditing e limitazioni
di accesso 
	\begin{itemize}
	\item \textbf{Classe C1}: Sicurezza Discrezionale, prevede la separazione degli utenti e dei dati. Incorpora
	un sistema di controllo in grado di limitare l'accesso alle risorse tramite la gestione dei permessi quindi
	definire quali utenti possono accedere a quali dati
	\item \textbf{Classe C2}: Protezione a Controllo di Accesso, aumenta il livello di granularit\'a potendo verificare
	le operazioni eseguite dagli utenti quali procedure di login, logging di eventi rilevanti per la sicurezza.
	Il sistema di Auditing cade proprio in questo gruppo, viene infatti descritto nelle sue funzionalit\'a 
	principali:
		\begin{itemize}
		\item Il sistema deve essere in grado di creare, mantenere e proteggere da modifiche o accessi
		indesiderati un file contenete il logging di eventi. 
		\item Deve essere possibile registrare i seguenti eventi:
			\begin{itemize}
			\item identificazione/autenticazione
			\item introduzione di oggetti nello spazio di memoria assegnato ai vari utenti (creazione di file,
			inizializzazione di processi)
			\item eliminazione di oggetti
			\item operazioni effettuate dall'amministratore di sistema e dagli addetti alla sicurezza
			\end{itemize}
		\item Pero ogni evento il sistema deve essere in grado di tracciare:
			\begin{itemize}
			\item data e tempo di esecuzione dell'evento
			\item utente
			\item tipo di evento
			\item successo/insuccesso dell'evento
			\end{itemize}
		\item Per operazioni di identificazione/autenticazione si deve anche tener traccia dell'ID del terminale
		dal quale \'e stato creato l'evento
		\item Per operazioni di creazione o elminiazione degli oggetti il sistema deve essere in grado di 
		memorizzare anche il nome dell'oggetto
		\item Il sistema di Auditing deve essere in grado di tracciare gli eventi eseguiti da ogni singolo utente
		\end{itemize}
	\end{itemize}
\item \textbf{Divisione B}: Protezione Mandatoria, il sistema deve essere in grado di assegnare un'etichetta alle strutture
principali del sistema. L'addetto alla sicurezza deve poter essere in grado di attivare la policy di sicurezza opportuna.
	\begin{itemize}
	\item \textbf{Classe B1}: Sicurezza a Etichette, il sistema deve contenere gli standard C2 inoltre devono essere
	presenti le seguenti cose:
		\begin{itemize}
		\item un documento informale che elenchi le policy di sicurezza attivabili sul sistema
		\item l'etichettatura delle strutture piu` importanti
		\item un controllo ad accesso mandatorio sugli oggetti 
		\end{itemize}
	\item \textbf{Classe B2}: Protezione Strutturata, deve estendere l'etichettatura esposta nella classe B1 a 
	tutte le strutture del sistema, vengono imposte configurazioni stringenti e i meccanismi di autenticazione sono
	pi\'u complessi. Il sistema deve essere relativamente resistente alle penetrazioni da parte di utenti maliziosi
	\item \textbf{Classe B3}: Domini di Sicurezza, le parti da controllare devono essere limitate in modo da poter
	eseguire dei test sul grado di sicurezza del codice che deve essere semplificato il pi\'u possibile durante la
	fase di ingegnerizzazione. Il sistema di Auditing deve essere esteso anche agli eventi dei segnali rilevanti per
	la sicurezza del sistema. Vengono richieste le procedure di recovery. Il sistema deve essere molto resistente 
	agli attacchi.
	\end{itemize}
\item \textbf{Divisione A}: Protezione Verificata, il sistema \'e caratterizzato dall'utilizzo di metodi formali per
verificare il corretto funzionamento dei sistemi di protezione ad accesso mandatorio e discrezionale al fine di 
classificare e proteggere le informazioni presenti nel sistema. \'E necessaria una documentazione estesa per dimostrare
che il sistema soddisfa i requisiti di sicurezza in tutti i suoi aspetti dal design, allo sviluppo fino 
all'implementazione finale dell'impianto.
	\begin{itemize}
	\item \textbf{Classe A1}: Progettazione Verificata, Protezione Verificata, il sistema implementa le stesse 
	funzionalit\'a dei sistemi di classe B3 tuttavia questi standard vengono curati sin dalle prime fasi di 
	progettazione del sistema in modo che rispecchino accuratamente le specifiche richieste dalla TCSEC.
	\end{itemize}
\end{itemize}


\section{Il formato OpenBSM}
In questa sezione verr\'a illustrato il formato OpenBSM.\\
\\
Il formato scelto per i l'Auditing \'e un formato definito da SUN Microsystem come parte integrante di BSM
\footnote[3]{BSM: Basic Security Module}. Il formato OpenBSM \'e stato progettato per essere indipendente dall'architettura
del processore.\\
Il log di eventi in formato OpenBSM \'e costituito da uno o pi\'u \textit{audit record}. Ogni \textit{record} \'e composto
da uno o pi\'u \textit{token} quali:
\begin{itemize}
\item \textbf{header}: informazioni generali quali
	\begin{itemize}
	\item evento di auditing
	\item lunghezza del record
	\item tipo di evento
	\item ora e tempo di esecuzione
	\end{itemize}
\item \textbf{token ... token} (eventualmente pi\'u di uno) rappresentati il tipo di oggetto loggato e le informazioni
estrapolate da esso.
\item \textbf{subject}: informazioni del processo quali IDs e PID
\item \textbf{return}: contiene il valore di ritorno della systemcall con notifica di successo/insuccesso
\item \textbf{trailer}: \'e il token di chiusura del record
\end{itemize}
La trasmissione dei \textit{record} in formato OpenBSM dal kernel verso il demone di auditing avviene codificando 
questi blocchi di dati in \textit{big endian} in modo da garantire un ulteriore grado di sicurezza dato da una 
comunicazione in formato binario e non in \textit{plain text}. A User Space sono pertanto presenti un set di librerie
in grado di decodificare il formato binario estrapolando il \textit{record} OpenBSM in formato 
\textit{human readable} tramite l'applicativo \textbf{praudit}.

\section{Implementazione in Linux}
In questa sezione viene trattata l'implementazione del sistema di Auditing nel kernel di Linux.

\subsection{System Call in Linux}
Al fine di tracciare le chiamate delle system call \'e necessario capire il funzionamento delle stesse.
In \figurename~\ref{fig:syscall1} e in \figurename~\ref{fig:syscall2} viene schematizzato il funzionamento di 
una system call.

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{syscall1.png}
\caption{Schema generale di funzionamento di una System Call}
\label{fig:syscall1}
\end{center}
\end{figure}

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{syscall2.png}
\caption{Handler di una system call}
\label{fig:syscall2}
\end{center}
\end{figure}

Tutte le volte che viene chiamata una system call si entra nel contesto di un processo eseguito a kernel 
space. Nel kernel di Linux ogni processo viene rappresentato da un'istanza di una \textit{task\_struct}
inserita in una \textit{double linked list} ~\ref{fig:tsk}. I campi di questa struttura identificano 
interamente e univocamente il processo pertanto sono utili al fine dell'attivit\'a di Auditing. L'idea
\'e infatti quella di catturare queste istanze all'atto della chiamata delle system call al fine di 
trascrivere queste informazioni in pacchetti da inviare al demone di Auditing a user space.\\

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{tsk.png}
\caption{Double-Linked List di \textit{task\_struct}}
\label{fig:tsk}
\end{center}
\end{figure}

\subsection{Kernel Space: Red Hat Linux-Audit}

L'implementazione del sistema di Auditing sotto Linux \'e stata oggetto di numerose revisioni. Essendo
costantemente sviluppato da RedHat e dall'NSA\footnote[4]{NSA: National Security Agency} \'e stato reso 
compatibile con il sottosistema SE Linux\footnote[5]{SE Linux: Security-Enhanced Linux}, tuttavia il 
logging avviene in semplice \textit{plain text}.\\
Linux-Audit \'e suddiviso nei seguenti file sorgenti:

\begin{itemize}
\item \textit{kernel/audit.h}, libreria contenente vari prototipi di funzioni e alcune strutture dati
di controllo
\item \textit{kernel/audit.c}, contiene le funzioni che gestiscono l'inizializzazione del sistema di
auditing e quelle che gestiscono il protocollo di comunicazione kernel space - user space
\item \textit{kernel/auditsc.c}, contiene le funzioni che implementano le regole di auditing, quindi
coloro che catturano le informazioni necessarie da mandare a user space
\item \textit{kernel/audit\_tree.c}, gestisce l'albero delle regole di auditing
\item \textit{kernel/auditfilter.c}, gestisce le regole di auditing inviate da user space
\end{itemize}

\subsubsection{Auditing delle System Call}

Quando si chiama una system call il kernel di linux richiama una routine scritta in assembly, quindi
\textit{architecture dependent}, il cui compito \'e quello di far entrare il sistema in modalit\'a
\textit{supervisor} e di eseguire l'operazione richiesta. Questo \'e il momento in cui viene loggato
il contesto del processo tramite una chiamata a una funzione che a sua volta richiama la funzione
\textit{audit\_syscall\_entry} presente in \textit{kernel/auditsc.c}. \\
Il codice riportato \'e quello per piattaforma x86.\\
In \textit{arch/x86/ia32/ia32entry.S} \'e posizionato il codice che richiama la modalit\'a
\textit{supervisor}:

\begin{lstlisting}
ENTRY(ia32_sysenter_target)
	...
	jnz  sysenter_tracesys
sysenter_tracesys:
        CFI_RESTORE_STATE
        xchgl   %r9d,%ebp
        SAVE_REST
        CLEAR_RREGS
        movq    %r9,R9(%rsp)
        movq    $-ENOSYS,RAX(%rsp)/* ptrace can change this for 
					a bad syscall */
        movq    %rsp,%rdi        /* &pt_regs -> arg1 */
        call    syscall_trace_enter
        LOAD_ARGS32 ARGOFFSET  /* reload args from stack in 
				case ptrace changed it */
        RESTORE_REST
        xchgl   %ebp,%r9d
        cmpl    $(IA32_NR_syscalls-1),%eax
        ja      int_ret_from_sys_call /* sysenter_tracesys has 
					set RAX(%rsp) */
        jmp     sysenter_do_call
        CFI_ENDPROC
ENDPROC(ia32_sysenter_target)
\end{lstlisting}

Da questa porzione di codice \'e possibile vedere la chiamata \textit{syscall\_trace\_entry} che 
richiama la routine presente in \textit{arch/x86/kernel/ptrace.c}, anch'essa 
\textit{architecture dependent}, il cui codice \'e il seguente:

\begin{lstlisting}
asmlinkage void syscall_trace_enter(struct pt_regs *regs)
{
        /* do the secure computing check first */
        secure_computing(regs->orig_ax);

        if (test_thread_flag(TIF_SYSCALL_TRACE)
            && (current->ptrace & PT_PTRACED))
                syscall_trace(regs);

        if (unlikely(current->audit_context)) {
                if (test_thread_flag(TIF_IA32)) {
                        audit_syscall_entry(AUDIT_ARCH_I386,
                                         regs->orig_ax,
                                         regs->bx, regs->cx,
                                         regs->dx, regs->si);
                } else {
                        audit_syscall_entry(AUDIT_ARCH_X86_64,
                                         regs->orig_ax,
                                         regs->di, regs->si,
                                         regs->dx, regs->r10);
                }
        }
}
\end{lstlisting}

La porzione di codice assembly che richiama la routine della system call \'e definita in 
\textit{arch/x86/kernel/entry\_32.S}:

\begin{lstlisting}
ENTRY(system_call)
	...
        jnz syscall_trace_entry
	...
syscall_trace_entry:
        movl $-ENOSYS,PT_EAX(%esp)
        movl %esp, %eax
        xorl %edx,%edx
        call do_syscall_trace
        cmpl $0, %eax
        jne resume_userspace            
        movl PT_ORIG_EAX(%esp), %eax
        cmpl $(nr_syscalls), %eax
        jnae syscall_call
        jmp syscall_exit
END(syscall_trace_entry)
\end{lstlisting}

\textit{syscall\_trace\_entry} richiama la routine \textit{do\_syscall\_trace} implementata 
anch'essa in \textit{arch/x86/kernel/ptrace.c}. Questa funzione richiama 
\textit{audit\_syscall\_exiti()} posizionata in \textit{kernel/auditsc.c}.\\
Il compito principale delle funzioni \textit{audit\_syscall\_entry()} e 
\textit{audit\_syscall\_exit()} \'e quello di copiare le informazioni del processo corrente
all'interno di una struttura dati creata ad hoc nel sistema di Auditing di Linux di nome
\textit{audit\_context}:

\begin{lstlisting}
struct audit_context {
        int                 dummy;/*must be the first element*/
        int                 in_syscall;
        enum audit_state    state;
        unsigned int        serial;/*serial number for record*/
        struct timespec     ctime; /* time of syscall entry */
        int                 major;         /* syscall number */
        unsigned long       argv[4];    /* syscall arguments */
        int                 return_valid;/* return code valid*/
        long                return_code;/*syscall return code*/
        int                 auditable;
        int                 name_count;
        struct audit_names  names[AUDIT_NAMES];
        char *              filterkey;
        struct path         pwd;
        struct audit_context *previous; /*For nested syscalls*/
        struct audit_aux_data *aux;
        struct audit_aux_data *aux_pids;

                   /* Save things to print about task_struct */
        pid_t               pid, ppid;
        uid_t               uid, euid, suid, fsuid;
        gid_t               gid, egid, sgid, fsgid;
        unsigned long       personality;
        int                 arch;

        pid_t               target_pid;
        uid_t               target_auid;
        uid_t               target_uid;
        unsigned int        target_sessionid;
        u32                 target_sid;
        char                target_comm[TASK_COMM_LEN];

        struct audit_tree_refs *trees, *first_trees;
        int tree_count;
};
\end{lstlisting}

\subsubsection{Formattazione dei Dati}

In \figurename~\ref{fig:audit} sono mostrate graficamente le chiamate a funzioni per generare
una lista di informazioni in \textit{plain text} contenenti i dati estrapolati dai contesti
dei processi loggati. Le informazioni legate allo stesso processo vengono inserite in una 
struttura \textit{socket buffer} la quale a sua volta \'e puntata da un'altra struttura 
\textit{audit\_buffer} inserita in una lista in attesa di essere spedita a user space. 

\begin{lstlisting}
struct audit_buffer {
        struct list_head     list;
        struct sk_buff      *skb;/*formatted skb ready to send*/
        struct audit_context *ctx;/*NULL or associated context*/
        gfp_t                gfp_mask;
};
\end{lstlisting}

\newpage
\begin{figure}
\begin{center}
\includegraphics[scale=.6]{audit.png}
\caption{Diagramma di Flusso delle funzioni chiamate per il Logging delle informazioni
a Kernel Space}
\label{fig:audit}
\end{center}
\end{figure}

La scrittura delle informazioni nella \textit{socket buffer} avviene mediante l'utilizzo 
della funzione \textit{vsnprintf()} presente nelle API del kernel di Linux. 

\subsubsection{Comunicazione Kernel Space - User Space}

Il sistema di comunicazione kernel space - user space si appoggia sulle \textit{netlink socket} 
sicuramente pi\'u versatili di un \textit{character/block device} o dell'utilizzo di \textit{procfs}. 
In \tablename~\ref{tbl:pvsn} vengono illustrate le caratteristiche di entrambe gli approci.\\
\begin{table}
\begin{center}
\begin{tabular}{|c|c|}
\hline
Procfs				  &		Netlink		\\
\hline
Basato su un filesystem           & Un'unica connessione netlink \\
richiede la creazione di un file  & puo' essere usata per trasferire \\
per ogni dato salvato             & pi\'u dati 				\\
\hline
Richiede numerose operazioni di   & Viene aperta un'unica socket \\ 
open/read/write/close             & utilizzata da tutti i dati   \\
\hline
Le notifiche sono complesse       & Le notifiche sono semplici e i  \\
(tramite inotify)                 & dati possono essere in unicast  \\ 
				  & o in broadcast                	\\
\hline
\end{tabular}
\caption{Procfs vs. Netlink Socket}
\label{tbl:pvsn}
\end{center}
\end{table}

Le informazioni, dopo essere state inserite nella \textit{sk\_buff}, vengono gestite tramite una coda in
attesa che il demone a user space sia pronto per ricevere i dati. A questo punto viene eseguito un thread
il cui compito e` quello di spedire i messaggi netlink gi\'a formattati verso il demone. Questo
processo viene illustrato dettagliatamente in \figurename~\ref{fig:flowlog}

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{flowlog.png}
\caption{Diagramma di Flusso rappresentante l'interazione Kernel Space - User Space}
\label{fig:flowlog}
\end{center}
\end{figure}

\subsection{User Space: Red Hat Auditd}

A user space \'e presente un demone in ascolto sulla socket con un duplice scopo:

\begin{itemize}
\item inviare le regole di auditing al kernel in modo da loggare solo un sottoinsieme di system call a scelta
dell'amministratore di sistema
\item salvare gli eventi di auditing in appositi file di log in formato testuale
\end{itemize}

\section{Implementazione in FreeBSD}
In questa sezione viene trattata l'implementazione dell'Auditing nel kernel di FreeBSD ponendo particolare
enfasi sul formato OpenBSM. Verr\'a tralasciata appositamente l'implementazione dell'Auditing delle system call
a basso livello in quanto non risulta essere rilevate ai fini del progetto. Il codice del kernel di FreeBSD
\'e stato studiato unicamente per apprendere la gestione del formato OpenBSM e l'integrazione di questo con 
gli eventi provenineti dalle system call. 

\subsection{Struttura del Progetto}

Dal 2006 il kernel di FreeBSD supporta l'Auditing delle system call tramite il formato OpenBSM. Il progetto
si articola su pi\'u file sorgenti in diverse directory:

\begin{itemize}
\item \textit{sys/bsm/}
        \begin{itemize}
        \item \textit{audit.h}, contiene strutture dati divise per tipo di evento loggato
        \item \textit{audit\_internal.h}, contiene le strutture dati fondamentali e le macro per per codificare
il \textit{plain text} in big endian
        \item \textit{audit\_kevents.h}, contiene le macro per tutti gli eventi di logging supportati dal
formato OpenBSM
        \item \textit{audit\_record.h}, contiene le macro per identificare tutti i possibili \textit{token}
creati dal formato OpenBSM
        \end{itemize}
\item \textit{sys/security/audit/}
        \begin{itemize}
        \item \textit{audit.h}, contiene i wrapper per le funzioni di logging in entrata e uscita dalle system call
e le maschere per gli argomenti loggati
        \item \textit{audit.c}, inizializzazione del sottosistema di auditing e gestione delle funzioni di logging
in entrata e uscita dalle system call
        \item \textit{audit\_bsm.c}, funzioni per la creazione del \textit{record} OpenBSM
        \item \textit{audit\_bsm\_token.c}, funzioni per la creazione dei \textit{token} richiamate dalle funzioni
presenti in \textit{audit\_bsm.c}
        \item \textit{audit\_syscalls.c}, contiene il codice delle nuove system call implementante nel sottosistema
di auditing
        \item \textit{audit\_pipe.c}, \textit{audit\_trigger.c}, \textit{audit\_worker.c}, gestiscono i
\textit{character device: /dev/audit} e \textit{/dev/auditpipe} che hanno il compito di gestire la trasmissione
dei dati Kernel Space - User Space quali regole di auditing e \textit{record} OpenBSM in formato binario.
        \end{itemize}
\end{itemize}

\subsection{Strutture Dati fondamentali}

Al fine di gestire il logging del formato OpenBSM \'e stato deciso di implementare due strutture dati il cui
compito \'e quello gestire rispettivamente i \textit{token} e i \textit{record}.

\begin{lstlisting}
struct au_token {
        u_char                  *t_data;
        size_t                   len;
        TAILQ_ENTRY(au_token)    tokens;
}

struct au_record {
        char                     used;
        int                      desc;
        TAILQ_HEAD(, au_token)   token_q;
        u_char                  *data;
        size_t                   len;
        LIST_ENTRY(au_record)    au_rec_q;
}
\end{lstlisting}

La creazione del \textit{record} OpenBSM avviene nel seguente modo:\\
Viene richiamata la funzione \textit{kaudit\_to\_bsm()} posta in \textit{sys/security/audit/audit\_bsm.c} la
quale \'e un'insieme di switch/case che vanno a verificare l'evento loggato al fine di richiamare la funzione
corretta per la gestione di questo.
\begin{lstlisting}
kaudit_to_bsm(struct kaudit_record *kar,struct au_record **pau)
{
        struct au_token *tok, *subj_tok;
        struct au_record *rec;
        au_tid_t tid;
        struct audit_record *ar;
	...
	ar = &kar->k_ar;
	rec = kau_open();

	switch (ar->ar_subj_term_addr.at_type) {
	...
	default:
	         bzero(&tid, sizeof(tid));
                 subj_tok = au_to_subject32(ar->ar_subj_auid,
                     ar->ar_subj_cred.cr_uid,
                     ar->ar_subj_egid,
                     ar->ar_subj_ruid,
                     ar->ar_subj_rgid,
                     ar->ar_subj_pid,
                     ar->ar_subj_asid,
                     &tid);
	}
	switch(ar->ar_event) {
	...
		if (ARG_IS_VALID(kar, ARG_FD)) {
                         tok = au_to_arg32(1, "fd", 
				ar->ar_arg_fd);
                         kau_write(rec, tok);
                 }
	...
	case AUE_SETGID:
                 if (ARG_IS_VALID(kar, ARG_GID)) {
                         tok = au_to_arg32(1, "gid", 
				ar->ar_arg_gid);
                         kau_write(rec, tok);
                 }
                 break;
	...
	default:
                 printf("BSM conversion requested for unknown 
			"event %d\n", ar->ar_event);
 
                 /*
                  * Write the subject token so it is properly 
		  * freed here.
                  */
                 kau_write(rec, subj_tok);
                 kau_free(rec);
                 return (BSM_NOAUDIT);
         }
 
         kau_write(rec, subj_tok);
         tok=au_to_return32((char)ar->ar_errno, ar->ar_retval);
         kau_write(rec, tok);
 
         kau_close(rec, &ar->ar_endtime, ar->ar_event);
	...
}
\end{lstlisting}

Da un'attenta analisi si capisce come viene costruito il \textit{record} OpenBSM:

\begin{itemize}
\item \textit{kau\_open()} per istanziare il la struttura \textit{au\_record}
\item \textit{au\_to\_subject32()} per scrivere il \textit{token}: subject
\item una serie di \textit{au\_to\_arg32()} per scrivere i vari \textit{token}
\item \textit{au\_to\_return32()} per scrivere il \textit{token}: return
\item \textit{kau\_close()} per scrivere i \textit{token}: headear e trailer
\item tutte queste operazioni sono intervallate da delle chiamate a \textit{kau\_write()} 
il cui scopo \'e quello di aggiungere il \textit{token} scritto, alla lista di \textit{au\_token}
puntata da \textit{au\_record}. 
\end{itemize}

\subsection{Comunicazione Kernel Space - User Space}

Nel kernel di FreeBSD \'e stato deciso di implementare una comunicazione Kernel Space - User Space
tramite un \textit{character device}. 

\subsubsection{Character Device: Introduzione}
\'E un file speciale al quale si puo' accedere con un \textit{stream} di byte. Essendo un driver
generalmente implementa alcune system call quali ad esempio \textit{open, close, read, write}. 
L'unica distinzione rilevante tra un file regolare e un \textit{character device} \'e che nel primo
si \'e sempre in grado di muoversi avanti e indietro tra i byte mentre il secondo, in genere, 
viene utilizzato solo com un canale di dati al quale \'e possibile accedere solo sequenzialmente.
I char device sono posizionati in \textit{/dev}.

\subsubsection{Character Device: Strutture Fondamentali}
Per poter scrivere un \textit{character device} bisogna introdurre concetti di programmazione ad
oggeti in C. All'interno del kernel, un char dev \'e visto come una struttura i cui campi sono
dei puntatori a funzioni. L'oggetto \'e pertanto rappresentato dall'istanza della \textit{cdevsw}
e i metodi sono le funzioni puntate dai campi della struttura. Di seguito viene rappresentata
la struttura cos\'i come definita in \textit{sys/sys/conf.h} e i prototipi puntati dai puntatori
in essa contenuti.\\

Prototipi delle funzioni:
\begin{lstlisting}
typedef int d_open_t(struct cdev *dev, int oflags, int devtype, 
			struct thread *td);
typedef int d_fdopen_t(struct cdev *dev, int oflags, 
			struct thread *td, struct file *fp);
typedef int d_close_t(struct cdev *dev, int fflag, int devtype, 
			struct thread *td);
typedef void d_strategy_t(struct bio *bp);
typedef int d_ioctl_t(struct cdev *dev, u_long cmd, 
		caddr_t data, int fflag, struct thread *td);
typedef int d_read_t(struct cdev *dev, struct uio *uio, 
			int ioflag);
typedef int d_write_t(struct cdev *dev, struct uio *uio, 
			int ioflag);
\end{lstlisting}

Campi della struttura:
\begin{lstlisting}
struct cdevsw {
        int                     d_version;
        u_int                   d_flags;
        const char              *d_name;
        d_open_t                *d_open;
        d_fdopen_t              *d_fdopen;
        d_close_t               *d_close;
        d_read_t                *d_read;
        d_write_t               *d_write;
        d_ioctl_t               *d_ioctl;
        d_poll_t                *d_poll;
        d_mmap_t                *d_mmap;
        d_strategy_t            *d_strategy;
        dumper_t                *d_dump;
        d_kqfilter_t            *d_kqfilter;
        d_purge_t               *d_purge;
        d_spare2_t              *d_spare2;
        uid_t                   d_uid;
        gid_t                   d_gid;
        mode_t                  d_mode;
        const char              *d_kind;
 
        /* These fields should not be messed with by drivers */
        LIST_ENTRY(cdevsw)      d_list;
        LIST_HEAD(, cdev)       d_devs;
        int                     d_spare3;
        union {
                struct cdevsw           *gianttrick;
                 SLIST_ENTRY(cdevsw)     postfree_list;
         } __d_giant;
};
\end{lstlisting}

\subsubsection{Character Device: Implementazione in FreeBSD}

La gestione del \textit{character device /dev/audit} \'e stata implementata in 
\textit{sys/security/audit/audit\_trigger.c}. Di seguito viene esposta la dichiarazione
dell'oggetto i cui campi sono i nomi dei metodi implementati per la gestione
del dispositivo.

\begin{lstlisting}
static struct cdevsw audit_cdevsw = {
        .d_version =    D_VERSION,
        .d_open =       audit_open,
        .d_close =      audit_close,
        .d_read =       audit_read,
        .d_write =      audit_write,
        .d_name =       "audit"
};
\end{lstlisting}

Il kernel di FreeBSD fornisce un'interfaccia standard per istanziare il dispositivo tramite
la funzione \textit{make\_dev()}.
\begin{lstlisting}
static void
audit_trigger_cdev_init(void *unused)
{

        /* Create the special device file. */
        audit_dev = make_dev(&audit_cdevsw, 0, UID_ROOT, 
		GID_KMEM, 0600, AUDITDEV_FILENAME);
}
\end{lstlisting}

I singoli metodi vengono richiamati ogni volta che viene richiesta quella determinata operazione.
Per evitare la modifica dei \textit{record} OpenBSM da parte di programmi maligni a user space, il metodo 
\textit{audit\_write} \'e stato solo dichiarato al fine di rendere il dispositivo solo un canale dati
da Kernel Space verso User Space.\\
Il demone a user space deve per\'o avere la possibilit\'a di interagire con il sottosistema di Auditing
a kernel space al fine di gestire le regole e le modalit\'a di logging. Per questo scopo sono state
introdotte alcune system call definite in \textit{sys/security/audit/audit\_syscalls.c}. \'E proprio questo
il problema cruciale. In generale si sconsiglia caldamente l'aggiunta di system call in modo da limitare
la quantit\'a di codice in grado di accedere a kernel space tramite richieste esplicite da user
space. Tuttavia si \'e ritenuto sicuro il codice aggiunto permettendo al demone \textbf{auditd} di modicifare
le regole tramite la system call \textit{auditon()}. 

\subsubsection{User Space: TrustedBSD Auditd}



\chapter{Requisiti e Specifiche}

\section{Integrazione del Formato OpenBSM nel kernel di Linux}
Al fine di garantire piena compatibilit\'a con il codice preesistente nel sottosistema di linux-audit
\'e stato deciso di aggiungere il formato OpenBSM come opzione di logging al demone auditd ufficiale.
Questo significa:

\begin{itemize} 
\item garantire compatibilit\'a con le opzioni gi\'a presenti
\item utilizzare il medesimo protocollo di comunicazione dell'attuale sistema di linux-audit
\item wrappare le strutture dati create dentro le struttre dati gi\'a esistenti in modo da dover aggiungere
meno codice e meno funzioni possibili
\item creare una patch per il sottosistema di linux-audit 
\item creare una patch per il demone in user space per gestire il formato di logging OpenBSM
\end{itemize}

I vantaggi che nascono da tali decisioni sono molteplici:

\begin{itemize}
\item Non vengono creati moduli ad hoc su cui \'e stato svolto poco testing e che potrebbero portare ad eventuali
instabilit\'a o crash del sistema
\item Possiblit\'a di integrazione della patch nell'albero ufficiale del kernel di linux
\item La patch viene applicata a codice che viene costantemente mantenuto e aggiornato ad ogni rilascio del kernel
\item Non bisogna disattivare il demone ufficiale per poter attivare il demone scritto ad hoc per il formato
OpenBSM 
\item Aggiunta di un formato binario per l'Auditing delle system call che da tempo viene richiesto dagli
sviluppatori/utilizzatori dello strumento di Auditing ufficiale.
\end{itemize}

Tuttavia non mancano gli svantaggi legati a questa scelta:

\begin{itemize}
\item Lo studio approfondito di TUTTO il codice del sottosistema di Auditing di Linux risulta lungo e intricato dovuto 
alla complessit\'a di un software maturo che contiene numerose funzionalit\'a
\item La progettazione del codice per integrarlo perfettamente con le strutture dati, i protocolli e le funzionalit\'a 
gi\'a implementate risulta complessa e lenta
\item La fase di testing/debugging \'e complicata dall'integrazione della patch con il codice preesistente
\end{itemize}

Dalle fasi di studio e progettazione sono stati indentificati i requisiti essenziali:
\begin{itemize}
\item Modulo a kernel space
\item wrappers di liste a kernel space per facilitare la gestione delle informazioni catturate
\item Socket Buffers per incapsulare le informazioni da spedire a kernel space
\item Netlink Sockets per il trasferimento di informazioni kernel space/user space
\end{itemize}

Nelle prossime sezioni verranno illustrati i punti precedenti.

\section{Modulo a Kernel Space in Linux 2.6}
Requisito fondamentale affinch\'e il sistema di auditing venga caricato nel kernel \'e scrivere
un modulo compatibile con Linux 2.6\\
\\
Di seguito viene illustrato il codice di un semplice modulo per il kernel 2.6\\

\begin{lstlisting}
#include <linux/init.h>
#include <linux/module.h>

static int __init test_module_init(void)
{
	printk(KERN_ALERT "Test_module is loaded" 
		"into the kernel\n");
	return 0;
}

static void __exit test_module_exit(void)
{
	printk(KERN_ALERT "Test_mnodule is exiting\n");
}

module_init(test_module_init);
module_exit(test_module_exit);
\end{lstlisting}

\begin{itemize}
\item le librerie incluse sono in linux-2.6.x/include
\item la funzione printk serve per stampare in console messaggi proveninti dal kernel in base
alla priorit\'a. Esistono 8 priorit\'a differenti impostabili dall'amministratore di sistema
sovrascivendo il primo valore in /proc/sys/kernel/printk (console\_loglevel). Dato un valore 
vengono stampate a video tutti i messaggi con priorit\'a pari o superiore. In 
\tablename~\ref{tbl:printk} sono elencate le priorit\'a in ordine di importanza.
\end{itemize}

\begin{table}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline
Priorit\'a   & Numero & Descrizione\\
\hline
KERN\_EMERG   & 0      & sistema inutilizzabile               \\  
KERN\_ALERT   & 1  & eseguire immediatamente \\
KERN\_CRIT    & 2  & condizione critica              \\
KERN\_ERR     & 3  & condizione di errore                 \\
KERN\_WARNING & 4  & condizione di attenzione              \\
KERN\_NOTICE  & 5  & condizione normale ma significativa \\
KERN\_INFO    & 6  & informazione                    \\
KERN\_DEBUG   & 7  & messaggi di debug            \\
\hline
\end{tabular}
\caption{Priorit\'a dei messaggi tramite printk}
\label{tbl:printk}
\end{center}
\end{table}

L'utilizzo delle printk \'e fontamentale per eseguire del debugging a kernel space. 

\section{Liste a Kernel Space}
Qualsiasi operazione a kernel space minimamente complesse richiede la conoscenza e l'utilizzo delle liste.
Le API del kernel di Linux offrono una serie di funzioni e strutture dati preconfezionate per gestire liste 
circolari definite in \textit{include/linux/list.h}. La struttura fondamentale \'e:

\begin{lstlisting}
struct list_head {
	struct list_head *next, *prev;
};
\end{lstlisting}

Di seguito il suo utilizzo in un codice di test:

\begin{lstlisting}
#include <linux/init.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/slab.h>

/* creating the type of my list elements */
struct buffer{
        /* this is REQUIRED for a kernel space
         * list implementation
         */
        struct list_head list; 
        char    string[30];
};

struct wrapper_buffer{
        struct buffer buf;
        int len;
};

static int __init list_init(void)
{
        struct buffer *buf_list, *buf;
        struct wrapper_buffer *wrp;
        struct list_head *pos, *q;
        int i;
        
        printk(KERN_ALERT "list_test2 is starting\n");
        wrp = kmalloc(sizeof(*wrp), GFP_KERNEL);
        buf_list = &(wrp->buf);
        INIT_LIST_HEAD(&(buf_list->list));
        wrp->len = 1;

        for(i = 0; i < 4; i++)
        {
                
                /* allocating space for the istance of struct 
		 * buffer that will be added to mylist and 
		 * working on it
                 */
                buf = kmalloc(sizeof(*buf), GFP_KERNEL);
                snprintf(buf->string, sizeof(buf->string), 
				"This is a test %d", i);
                
                /* adding the istance to mylist */
                list_add_tail(&(buf->list), &(buf_list->list));
        }

        /* printing the list items */
        printk(KERN_ALERT "list_for_each: \n");
        list_for_each(pos, &(buf_list->list))
        {
                buf = list_entry(pos, struct buffer, list);
                printk(KERN_ALERT "%s\n", buf->string);
        }

        /* printing the list items and freeing the space 
	 * allocated for them
         */
        printk(KERN_ALERT "list_for_each_safe: \n");
        list_for_each_safe(pos, q, &(buf_list->list))
        {
                buf = list_entry(pos, struct buffer, list);
                printk(KERN_ALERT "%s\n", buf->string);
                list_del(pos);
                kfree(buf);
        }

        return 0;
}
\end{lstlisting}

\begin{itemize}
\item \textit{kmalloc} \'e la kernel malloc. Rispetto al suo corrispettivo in user space ha un ulteriore parametro
che indica se lo spazio allocato viene gestito dal kernel o da un processo in user space tramite funzioni quali
\textit{copy\_to\_user()}. In questo caso si \'e voluto allocare spazio destinato unicamente al kernel per questo
\'e stata utilizzata la macro GFP\_KERNEL altrimenti sarebbe stata utilizzata la macro GFP\_USER. Esiste anche
la macro GFP\_ATOMIC utilizzata per operazioni atomiche (quelle eseguite in un unico ciclo di clock).
\item INIT\_LIST\_HEAD inizializza una lista di tipo \textit{list\_head}
\item \textit{list\_add\_tail()} aggiunge il primo parametro in coda alla lista definita nel secondo parametro
\item \textit{list\_for\_each()} \'e un wrapper a un ciclo \textit{for} per scorrere gli elementi della lista
\item \textit{list\_for\_each\_safe()} \'e simile a \textit{list\_for\_each()} con l'aggiunta di un parametro che
permette la cancellazione e la conseguente chiamata a \textit{kfree()} dell'oggetto per liberarne l'area di memoria
\end{itemize}

\section{Socket Buffer}
\label{sec:skb}
Tutti i dispositivi di rete siano essi driver o semplici connessioni vengono gestiti a kernel space
tramite una struttura fondamentale: \textbf{sk\_buff}. Essa \'e definita in \textit{include/linux/skbuff.h}.
Tutti i dati che devono essere trasferiti tramite un protocollo di rete devono essere wrappati dentro una socket
buffer la quale, a sua volta deve essere castata ad una struttura opportuna in base al protocollo utilizzato.
Nel caso del sistema di Auditing bisogna utilizzare una struttura dedicata al protocollo netlink il cui nome 
\'e \textbf{nlmsghdr} (NetLink MeSsaGe HeaDeR - \textit{include/linux/netlink.h}).

\begin{lstlisting}
struct sk_buff {
        /* These two members must be first. */
        struct sk_buff          *next;
        struct sk_buff          *prev;

        struct sock             *sk;
        ktime_t                 tstamp;
        struct net_device       *dev;

        union {
                struct  dst_entry       *dst;
                struct  rtable          *rtable;
        };
        struct  sec_path        *sp;

        /*
         * This is the control buffer. It is free to use for 
	 * every layer. Please put your private variables 
	 * there. If you want to keep them across layers you 
	 * have to do a skb_clone() first. This is owned by 
	 * whoever has the skb queued ATM.
         */
        char                    cb[48];

        unsigned int            len,
                                data_len;
        __u16                   mac_len,
                                hdr_len;
        union {
                __wsum          csum;
                struct {
                        __u16   csum_start;
                        __u16   csum_offset;
                };
        };
        __u32                   priority;
        __u8                    local_df:1,
                                cloned:1,
                                ip_summed:2,
                                nohdr:1,
                                nfctinfo:3;
        __u8                    pkt_type:3,
                                fclone:2,
                                ipvs_property:1,
                                peeked:1,
                                nf_trace:1;
        __be16                  protocol;

        void          (*destructor)(struct sk_buff *skb);
#if defined(CONFIG_NF_CONNTRACK) || 
		defined(CONFIG_NF_CONNTRACK_MODULE)
        struct nf_conntrack     *nfct;
        struct sk_buff          *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
        struct nf_bridge_info   *nf_bridge;
#endif

        int                     iif;
#ifdef CONFIG_NETDEVICES_MULTIQUEUE
        __u16                   queue_mapping;
#endif
#ifdef CONFIG_NET_SCHED
        __u16                   tc_index;     
#ifdef CONFIG_NET_CLS_ACT
        __u16                   tc_verd;      
#endif
#endif
#ifdef CONFIG_IPV6_NDISC_NODETYPE
        __u8                    ndisc_nodetype:2;
#endif
        /* 14 bit hole */

#ifdef CONFIG_NET_DMA
        dma_cookie_t            dma_cookie;
#endif
#ifdef CONFIG_NETWORK_SECMARK
        __u32                   secmark;
#endif

        __u32                   mark;

        sk_buff_data_t          transport_header;
        sk_buff_data_t          network_header;
        sk_buff_data_t          mac_header;
        /* These elements must be at the end, see 
	 * alloc_skb() for details.  */
        sk_buff_data_t          tail;
        sk_buff_data_t          end;
        unsigned char           *head,
                                *data;
        unsigned int            truesize;
        atomic_t                users;
};
\end{lstlisting}

\begin{lstlisting}
struct nlmsghdr
{
        __u32 nlmsg_len;	/* Length of message including 
					header */
        __u16 nlmsg_type;	/* Message content */
        __u16 nlmsg_flags;	/* Additional flags */
        __u32 nlmsg_seq;  	/* Sequence number */
        __u32 nlmsg_pid;  	/* Sending process port ID */
};
\end{lstlisting} 

Di seguito un semplice utilizzo di \textit{struct sk\_buff}:

\begin{lstlisting}
#include <linux/init.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include <linux/netlink.h>

#define BUFSIZE 1024

int len = 30;
int lenskb = 100;

static struct audit_buffer *log_start(void);

struct audit_buffer{
        struct list_head        list;
        struct sk_buff          *skb;
        gfp_t                   gfp_mask;
};

static int skbuff_init(void)
{
        int lenp = 0;
        struct sk_buff *skb;
        struct audit_buffer *ab_bsm;

        struct nlmsghdr *nlh = NULL;

        printk(KERN_ALERT "skbuff_test starting\n");
        ab_bsm = log_start();
        skb = ab_bsm->skb;
        
        lenp = snprintf(skb_tail_pointer(skb), len, 
			"This is a test");
        nlh = (struct nlmsghdr *)skb->data;
        printk(KERN_ALERT "%d %d: %s\n", 
		strlen("This is a test"), lenp,
			(char *)NLMSG_DATA(nlh));
        skb_put(skb, lenp);
        lenp = snprintf(skb_tail_pointer(skb), len, 
			"This is the test");
	printk(KERN_ALERT "%s\n", (char *)NLMSG_DATA(nlh));
        kfree(ab_bsm);
        return 0;
}

static struct audit_buffer *log_start(void)
{
        struct audit_buffer *ab_bsm = kmalloc(sizeof(*ab_bsm), 
						GFP_KERNEL);
        struct nlmsghdr *nlh = NULL;

        ab_bsm->skb = alloc_skb(BUFSIZE, GFP_KERNEL);
        nlh = (struct nlmsghdr *)skb_put(ab_bsm->skb, 
					NLMSG_SPACE(0));
        nlh->nlmsg_type = 0;
        nlh->nlmsg_flags = 0;
        nlh->nlmsg_pid = 0;
        nlh->nlmsg_seq = 0;
        return ab_bsm;
}

\end{lstlisting}

\'E importante sottolineare come anche le socket buffer siano gestite tramite le liste
esposte precedentemete. 
\begin{itemize}
\item \textit{alloc\_skb()} serve per allocare spazio di memoria alla struttura. A seguito
di questa operazione tutti i puntatori interni alla struct punteranno all'inizio dell'area
di memoria allocata quali: \textit{skb->tail skb->head skb->data}. Per capire meglio
l'inizializzazione della \textit{sk\_buff} \'e utile illustrare il codice di 
\textit{\_\_alloc\_skb()} definito in \textit{net/core/skbuff.c} e richiamato dalla stessa
\textit{alloc\_skb()}. In \figurename~\ref{fig:allocskb} viene visualizzata la gestione
dell'area di memoria a seguito della chiamata \textit{alloc\_skb()}

\begin{lstlisting}
struct sk_buff *__alloc_skb(unsigned int size, 
		gfp_t gfp_mask, int fclone, int node)
{
	...
        struct skb_shared_info *shinfo;
        struct sk_buff *skb;
        u8 *data;
	...
        memset(skb, 0, offsetof(struct sk_buff, tail));
        skb->truesize = size + sizeof(struct sk_buff);
        atomic_set(&skb->users, 1);
        skb->head = data;
        skb->data = data;
        skb_reset_tail_pointer(skb);
        skb->end = skb->tail + size;
        /* make sure we initialize shinfo sequentially */
        shinfo = skb_shinfo(skb);
        atomic_set(&shinfo->dataref, 1);
        shinfo->nr_frags  = 0;
        shinfo->gso_size = 0;
        shinfo->gso_segs = 0;
        shinfo->gso_type = 0;
        shinfo->ip6_frag_id = 0;
        shinfo->frag_list = NULL;
	...
}
\end{lstlisting}

\begin{figure}
\begin{center}
\includegraphics{allocskb.png}
\caption{Inizializzazione di \textit{sk\_buff} }
\label{fig:allocskb}
\end{center}
\end{figure}

\item \textit{skb\_put()} \'e definita in \textit{net/core/skbuff.c}. 
Di seguito lo pseudocodice relativo a questa funzione:

\begin{lstlisting}
unsigned char *skb_put(struct sk_buff *skb, 
				unsigned int len)
{
	unsigned chat *tmp = skb_tail_pointer(skb);
	SKB_LINEAR_ASSERT(skb);
	skb->tail += len;
	skb->len += len;
	if (error control)
	return tmp; 
}
\end{lstlisting}

Lo scopo principale \'e quello di aggiornare i puntatori \textit{skb->tail} e 
\textit{skb->len} con la lunghezza passata come parametro e di ritornare la prima locazione
libera all'interno di \textit{skb->data} tramite \textit{skb\_tail\_pointer()}.
\item \textit{skb\_put()} viene castata alla struttura \textbf{nlmsghdr} dopo aver allocato 
lo spazio per l'header in \textit{skb->data} tramite la macro NLMSG\_SPACE(0).
\item vengono riempiti tutti i campi dell'header
\item la macro NLMSG\_DATA() ha il compito di restituire il payload del messaggio netlink
\end{itemize}

\section{Netlink Socket}
\label{sec:netlink}
In questa sezione viene trattato l'implementazione di una netlink socket a kernel space.\\
\\
Le netlink socket possono funzionare sia in broadcast sia in unicast. Al fine di garantire un certo
grado di sicurezza il sistema di Auditing utilizza messaggi unicast indirizzati solo ed esclusivamente
al PID associato al demone che gestisce il logging degli eventi. I passi da seguire nell'implementazione
di una netlink socket sono:

\begin{itemize}
\item creare un pacchetto netlink a user space riempiendo l'header sia con il PID 0 che identifica il kernel
come destinatario del messaggio sia con il PID del demone a user space
\item a kernel space ricevere il pacchetto ed estrapolare dall'header il PID del demone 
\item la connessione \'e stabilita, il kernel utilizza il PID del demone come PID di destinazione dei sui messaggi
\end{itemize}

Di seguito il codice a user space per inviare un pacchetto netlink al kernel e riceverne la risposta
\begin{lstlisting}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <errno.h>

#define MAX_PAYLOAD 1024

int main()
{
        int sock_fd, len;
        struct sockaddr_nl dest_addr, src_addr;
        struct nlmsghdr *nlh;
        char buf[MAX_PAYLOAD];
        socklen_t addrsize = sizeof(src_addr);

        sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_UNUSED);
        memset(&dest_addr, 0, sizeof(dest_addr));
        memset(&src_addr, 0, sizeof(src_addr));

        /*filling the destination address*/
        dest_addr.nl_family = AF_NETLINK;
        dest_addr.nl_pid = 0; //destination is kernel space
        dest_addr.nl_groups = 0; //unicast
        
        /*filling the header*/
        nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
        nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
        nlh->nlmsg_pid = getpid(); //userspace app pid
        nlh->nlmsg_flags = 0;
        /*copying the message data*/
        strcpy(NLMSG_DATA(nlh), "Hello world");

        /*sending nlh through netlink socket*/
        sendto(sock_fd, nlh, nlh->nlmsg_len, 0, 
          (struct sockaddr *)&dest_addr, sizeof(dest_addr));
        
        /*receiving nlh through netlink socket*/
        len = recvfrom(sock_fd, buf, MAX_PAYLOAD, MSG_DONTWAIT, 
                (struct sockaddr *)&src_addr, &addrsize);
        printf("len: %d\n%s\n", len, strerror(errno));
        nlh = (struct nlmsghdr *)buf;
        printf("userspace app: %s\n strlen: %d\n", 
                (char *)NLMSG_DATA(nlh), 
 		strlen((char *)NLMSG_DATA(nlh)));
        close(sock_fd);
        return 0;
}
\end{lstlisting}

La gestione delle netlink socket a user space avviene come per qualsiasi altro protocollo di rete.\\

Invio del messaggio:
\begin{itemize}
\item Viene aperto un socket descriptor i cui parametri sono dati dal protocollo NETLINK, dal tipo di 
datagramma che vogliamo creare (SOCK\_RAW perch\'e \'e necessario riempire i campi dell'header), e infine
un valore che permette di idetificare la sessione. In questo caso \'e stato scelto l'utilizzo di 
NETLINK\_UNUSED e tale valore dovr\'a essere utilizzato sia dal kernel sia dal processo in user space per
poter dialogare.
\item Si riempie la struttura con l'indirizzo di destinazione data da:

	\begin{itemize}
	\item famiglia del protocollo: AF\_NETLINK
	\item PID di destinazione (0 per PID del kernel) 
	\item gruppo di destinazione (0 per connessioni unicast)
	\end{itemize}

\item Si casta l'area allocata per il payload a una struttura \textbf{nlmsghdr} esattamente come a kernel space
\item Si riempie l'header con la lunghezza del messaggio e il PID del processo in userspace 
\item Infine si invia il pacchetto al kernel tramite una semplice \textit{sendto()}
\end{itemize}

Ricezione del messaggio:
\begin{itemize}
\item Si rimane in ascolto tramite una \textit{recvfrom()} 
\item Quindi si casta il messaggio ricevuto in una struttura di tipo \textbf{nlmsghdr}
\item Infine si estrapola il payload tramite la macro NLMSG\_DATA()
\end{itemize}

Verr\'a ora illustrata la controparte a kernel space:
\begin{lstlisting}
static int __init netlink_init(void)
{	
	printk(KERN_ALERT "netlink_test is starting\n");
	nl_sk =netlink_kernel_create(&init_net, NETLINK_UNUSED, 
		0, netlink_receive, NULL, THIS_MODULE);
	if(!nl_sk)
		printk(KERN_ALERT "error while initiliazing"
			" netlink socket\n");
	return 0;
}

void netlink_receive(struct sk_buff *skb)
{
	struct nlmsghdr *nlh;

	nlh = (struct nlmsghdr *)skb->data;
	printk(KERN_ALERT "%s\n",(char *)NLMSG_DATA(nlh));
	/* userspace app pid */
	nlk_pid = NETLINK_CB(skb).pid;
	printk(KERN_ALERT "nlk_pid: %d\n", nlk_pid);
	netlink_send();
}

void netlink_send(void)
{
        struct sk_buff *skb;
        struct nlmsghdr *nlh;
        int a = strlen("Hi from the kernel");
        int b = strlen("Test 2");

        skb = alloc_skb(BUFFER, GFP_KERNEL);
        nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_SPACE(0));
        nlh->nlmsg_flags = 0;
        nlh->nlmsg_pid = 0;
        nlh->nlmsg_seq = 0;
        memcpy(skb_tail_pointer(skb), 
			"Hi from the kernel", a+1);
        skb_put(skb, a);
        memcpy(skb_tail_pointer(skb), 
				"Test 2", b+1);
        skb_put(skb, b);
        nlh->nlmsg_len = skb->len - NLMSG_SPACE(0);
        printk(KERN_ALERT "a: %d b: %d skb->len: %d\n", 
			a, b, skb->len - NLMSG_SPACE(0));
        netlink_unicast(nl_sk, skb, nlk_pid, 0);

}
\end{lstlisting}

\begin{itemize}
\item La socket viene creata tramite la funzione di libreria \textit{netlink\_kernel\_create} i cui 
parametri pi\'u importanti sono:

	\begin{itemize}
	\item \textbf{\&inet\_net}: \'e l'indirizzo di una \textbf{struct net}
	\item NETLINK\_UNUSED: protocollo usato (deve essere il medesimo anche nell'implementazione del demone
	a user space)
	\item \textit{netlink\_receive}: \'e l'indirizzo della routine adibita a ricevere messaggi da userspace 
	\end{itemize}

\item Quando si riceve un dato da user space viene richiamata la funzione \textit{netlink\_receive()} che svolge
le seguenti operazioni:
	
	\begin{itemize}
	\item casta il buffer contenente i dati ricevuti a una struttura di tipo \textbf{nlmsghdr} essendo un dato
	netlink
	\item estrapola il payload tramite la macro NLMSG\_DATA()
	\item estrapola il PID del demone a user space tramite la macro NETLINK\_CB()
	\item richiama la funzione per creare e spedire il messaggio di risposta
	\end{itemize}

\item Nella funzione \textit{netlink\_send()} \'e di fondamentale importanza inserire in \textit{nlh->nlmsg\_len}
la lunghezza del payload al fine di garantire una corretta ricezione e allineamento del messaggio 
\end{itemize}

\section{Thread a Kernel Space}
Spesso \'e necessario sincronizzare eventi asincroni. Queste operazioni possono essere svolte tramite l'utilizzo
di thread. L'utlizzo delle stesse netlink socket implica, per operazioni un po' complesse, l'utilizzo dei thread
per sicronizzare la creazione del payload con l'invio dei dati a seguito della ricezione del PID del demone a 
user space. Cerchiamo di comprendere meglio questo discorso con un esempio:\\
Finora il payload del messaggio \'e stato creato nel momento in cui veniva richiamata la funzione 
\textit{netlink\_send()} a seguito del riceviemnto del pacchetto da user space. Ma cosa succede se le operazioni
di creazioni del payload sono talmente complesse da richiedere un numero svariato di chiamate a funzioni e sono 
indipendenti dall'effettiva esecuzione del demone a user space? L'idea \'e quella di eseguire il codice per creare 
il payload a seguito della creazione della netlink socket. Mentre la routine \textit{netlink\_receive()} 
rimane in attesa del PID da user space il codice a kernel space deve essere in grado di svolgere le sue operazioni 
al fine di inviare il payload nel momento in cui il demone a user space viene attivato. Chiaramente l'invio del payload
implica la terminazione delle operazioni a kernel space. Per sincronizzare questi eventi \'e necessario utilizzare
i thread. 

\subsection{Un po' di teoria sui Thread}
Nel kernel di Linux tutti i thread vengono considerati processi standard, non viene pertanto fornita alcuna
struttura speciale per rappresentarli. Ci\'o significa che anche i thread vengono rappresentati tramite la classica
\textbf{task\_struct}. L'unica differenza tra i thread e i processi nel kernel di Linux \'e rappresentata dal fatto
che i thread condividono le medesime risorse.

\newpage
\subsection{Implementazione a Kernel Space}

\begin{figure}
\begin{center}
\includegraphics[scale=.5]{img1.png}
\caption{Diagramma dello stato dei processi}
\end{center}
\end{figure}

In figura \'e rappresentato lo stato dei processi di seguito la spiegazione:

\begin{itemize}
\item TASK\_RUNNING, il processo \'e pronto per essere mandato in esecuzione. Quando un processo si trova in questa
situazione o \'e in esecuzione oppure \'e nella coda di processi pronti per essere eseguiti.
\item TASK\_INTERRUPTIBLE, il processo \'e bloccato in attesa che qualche condizione si verifichi. Quando si verifica
l'evento atteso o vi \'e la ricezione di un segnale il processo torna ad essere TASK\_RUNNING.
\item TASK\_UNINTERRUPTIBLE, il processo \'e bloccato ma puo' tornare in TASK\_RUNNING solo a seguito di un evento atteso
e non a seguito di una ricezione di un segnale.
\item TASK\_ZOMBIE, il processo \'e terminato ma il descrittore deve essere ancora reperibile perch\'e il processo parent
non ha ancora chiamato la \textit{wait()}.
\item TASK\_STOPPED, l'esecuzione del processo \'e stata fermata.
\end{itemize}

Come visto, in Linux i processi TASK\_RUNNING vengono mantenuti in una 
\textit{run queue}. Quando la \textit{timeslice} di un processo in esecuzione
termina lo \textit{scheduler} manda in esecuzione il successivo processo in coda.
Ogni processo puo' richiedere volontariamente di essere bloccato e di mandare in
esecuzione un altro processo tramite la chiamata della funzione \textit{schedule()}.
Quando un processo viene richiamato l'esecuzione riprende dal punto in cui era stat
bloccata. \\
Per ottimizzare la gestione dei processi \'e opportuno introdurre le
\textit{wait queue}, meccanismi ad alto livello utilizzati per bloccare o risvegliare
l'esecuzione dei processi. \\
Le funzioni principali per la gestione dei thread sono le seguenti:
\begin{itemize}
\item DECLARE\_WAIT\_QUEUE\_HEAD(), inizializza una nuovo evento \textit{wait queue}
\item DECLARE\_WAITQUEUE(), inserisce un nuovo elemento nella coda
\item \textit{add\_wait\_queue()}, aggiunge il processo corrente alla coda
\item \textit{set\_currente\_state()}, imposta lo stato del processo
\end{itemize}

%\begin{figure}
%\begin{center}
%\includegraphics[scale=0.5]{img1.png}
%\caption{Diagramma dello stato dei processi}
%\end{center}
%\end{figure}

%esempio di codice mio
%spiegazione del codice

\subsection{Esempio di codice}

Di seguito l'implementazione delle netlink socket mediante l'utlizzo di thread:

\begin{lstlisting}
static struct task_struct *ksend_task;
static DECLARE_WAIT_QUEUE_HEAD(ksend_wait);

static int ksend_thread(void *dummy)
{
	DECLARE_WAITQUEUE(wait, current);
	set_current_state(TASK_INTERRUPTIBLE);
	add_wait_queue(&ksend_wait, &wait);
	if(!nlk_pid){
		schedule();
	}
	__set_current_state(TASK_RUNNING);
	remove_wait_queue(&ksend_wait, &wait);
	netlink_send();
	return 0;
}

void netlink_receive(struct sk_buff *skb)
{
	struct nlmsghdr *nlh;

	ksend_task = kthread_run(ksend_thread, NULL, "ksend");
	nlh = (struct nlmsghdr *)skb->data;
	printk(KERN_ALERT "%s\n", (char*)NLMSG_DATA(nlh));
	/* userspace app pid */
	nlk_pid = NETLINK_CB(skb).pid;
	printk(KERN_ALERT "nlk_pid: %d\n", nlk_pid);
	wake_up_interruptible(&ksend_wait);
}
\end{lstlisting}

\begin{itemize}
\item \textit{kthread\_run()}, i cui argomenti sono:
	\begin{itemize}
	\item puntatore alla routine del thread
	\item puntatore ai dati da passare alla routine del thread
	\item identificativo del thread
	\end{itemize}
\item A questo punto parte il thread e verifica se \textit{nlk\_pid}
\'e ancora == 0. In questo caso manda in \textit{sleep} il processo e richiama
\textit{schedule()} il quale mander\'a in esecuzione altri processi TASK\_RUNNING.
\item Quando \textit{netlink\_receive()} riceve il PID da user space viene chiamato
\textit{wake\_up\_interruptible()} che risveglia il thread. 
\item Il thread riprende la sua esecuzione e chiama \textit{netlink\_send()} dopo
aver tolto se stesso dalla coda di processi in attesa e aver ripristinato il prprio
stato come TASK\_RUNNING
\end{itemize}

\chapter{Implementazione}

\section{Architettura}

L'architettura del sistema sviluppato si divide in una porzione di codice sviluppato a kernel space
e un'altra porzione di codice sviluppata a user space. L'obiettivo dell'intero sistema \'e quello
di garantire la compatibilit\'a tra l'Auditing implementato nel kernel di Linux e i 
tool di OpenBSM. \\
In \figurename~\ref{fig:block} viene mostrato lo schema a blocchi che descrive il funzionamento
del sistema implementato. 

\begin{itemize}
\item \textit{bsm\_test.c} \'e il modulo di test costituito da:
	\begin{itemize}
	\item funzioni per scrivere in formato OpenBSM
	\item funzioni per creare un record OpenBSM
	\item funzioni per gestire la connessione netlink
	\end{itemize}
\item \textit{auditd} \'e il demone a user space il cui compito \'e quello di impostare le regole
di logging delle system call e di ricevere le informazioni dal kernel tramite la netlink socket; 
le funzionalit\'a di questo demone sono simulate da una piccola applicazione scritta ad hoc
\item \textit{praudit} \'e il tool contenuto nel pacchetto ufficiale di TrustedBSD per convertire
il formato OpenBSM in \textit{plain text}
\end{itemize}

Tutto il codice \'e stato scritto in piena conformit\'a con le funzionalit\'a offerte da linux-audit
e da auditd in modo da poter integrare successivamente il formato OpenBSM seguendo le linee guida
presentate nel modulo di test. Essendo linux-audit un codice complesso e maturo \'e stato deciso
di procedere con uno sviluppo di tipo icrementale e di testare le funzionalit\'a del formato OpenBSM
con un modulo di prova al fine di semplificare operazioni di debugging e di limitare i rischi 
relativi a \textit{race conditions} dovute alle numerose strutture dati con \textit{scope} globale.
Ci si \'e resi conto infatti di come fosse semplice riprodurre il protocollo di comunicazione utilizzato
in linux-audit per poi sviluppare il formato OpenBSM sotto Linux senza dover incappare in spiacevoli
modifiche del modulo ufficiale che avrebbero portato ad una instabilit\'a generale del sistema essendo
il modulo ufficiale caricato direttamente al boot e non un modulo caricabile esternamente.\\
Nelle prossime sezioni verranno esaminati i singoli moduli separatamente.

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{img2.png}
\caption{Schema a blocchi del sistema di Auditing}
\label{fig:block}
\end{center}
\end{figure}

\newpage
\section{Implementazione a Kernel Space}
Il codice a Kernel Space \'e stato diviso nei seguenti file:

\begin{itemize}
\item \textit{audit.h}, definizione di alcune strutture, tipi di dati e macro per il formato OpenBSM
\item \textit{audit\_internal.h}, definizione delle strutture dati fondamentali e delle funzioni
per tradurre \textit{plain text} in formato binario
\item \textit{test\_bsm.c}, modulo a kernel space
\end{itemize}

\subsection{Strutture Dati Fondamentali}

Al fine di mantenere le medesime funzioni implementate nel kernel di FreeBSD sono state portate 
le stesse strutture dati adottandole alle API del kernel di Linux. Di seguito le due strutture
dati principali.

\begin{lstlisting}
struct au_token {
	u_char			*t_data;
	size_t			 len;
	struct list_head	 list; 
	};

struct au_record {
	char			 used;	
	int			 desc;	
	struct au_token		 token_q;
	u_char			*data;
	size_t			 len;
	};

struct audit_buffer{
	struct list_head 	 list;
	struct sk_buff		*skb; 
	gfp_t			 gfp_mask;
	};
\end{lstlisting}

\begin{itemize}
\item \textit{au\_token}, i cui campi sono:
	\begin{itemize}
	\item un puntatore a char che punter\'a all'area di memoria contenente il \textit{token} in
	formato OpenBSM
	\item la lunghezza del token
	\item una struttura \textit{list\_head} per poter essere \textit{linkata} alla lista di 
	\textit{au\_token}
	\end{itemize} 
\item \textit{au\_record}, i cui campi sono:
	\begin{itemize}
	\item un char che identifica se l'instanza \'e in uso
	\item un descrittore del record (attualmente non utilizzato)
	\item la testa della lista di \textit{au\_token}
	\item un puntatore ad un area di memoria che verr\'a stanziata per serializzare il contenuto
	della lista di textit{au\_token}
	\item la lunghezza completa del record OpenBSM
	\end{itemize} 
\item \textit{audit\_buffer}, i cui campi sono:
	\begin{itemize}
	\item una struttura \textit{list\_head} per poter essere linkata ad altre strutture di tipo
	\textit{audit\_buffer} (inutilizzata nel test effettuato)
	\item una struttura \textit{sk\_buff} per poter wrappare i token serializzati al fine di spedirli
	a user space tramite l'utilizzo della netlink socket
	\item un campo che identifica se l'istanza corrente \'e di tipo GFP\_USER o GFP\_KERNEL
	\end{itemize}
\end{itemize}

In \figurename~\ref{fig:struct} si puo' notare come siano stati introdotti concetti di programmazione a oggetti.
Le strutture dati \textit{au\_record} e \textit{au\_token} sono solo delle astrazioni che, combinate 
all'utilizzo delle liste, semplificano la gestione delle informazioni. Si \'e voluto rendere \textit{au\_record}
un contenitore con un link alla lista di token ognuno dei quali viene creato a parte e aggiunto a questa.
Solo quando tutto il record \'e stato scritto, la lista viene svuotata e tutti i dati vengono serializzati
all'interno di un'area di memoria puntata da \textit{au\_record->data}. Questi stessi dati vengono 
conseguentemente wrappati all'interno di una struttura socket buffer e quindi castati a \textit{nlmsghdr}
in modo da poter trasmettere il record, in qualit\'a di payload, a user space tramite una netlink socket come
mostrato in \figurename~\ref{fig:wrap}.

Di fondamentale importanza risulta essere la macro per allocare spazio al token OpenBSM. Di seguito viene 
riportato il codice corrispondente:

\begin{lstlisting}
#define GET_TOKEN_AREA(t, dptr, length) do {	\
	t = kmalloc(sizeof(struct au_token), GFP_KERNEL);\
	t->t_data = kmalloc(length, GFP_KERNEL);	\
	t->len = length;				\
	dptr = t->t_data;				\
}while(0)
\end{lstlisting}

\begin{itemize}
\item t \'e una struct di tipo \textit{au\_token} 
\item dptr \'e un puntatore a char che punta alla prima locazione di memoria libera dove scrivere i dati
in binari relativi al token
\item length \'e la dimensione da allocare per il token
\end{itemize}

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{img3.png}
\caption{Strutture dati fondamentali, \textit{au\_record} contiene una lista di \textit{au\_token}
che vengono successivamente serializzate in \textit{au\_record->data}}
\label{fig:struct}
\end{center}
\end{figure}

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{img4.png}
\caption{Wrapper di \textit{au\_record->data} dentro \textit{audit\_buffer->sk\_buff}}
\label{fig:wrap}
\end{center}
\end{figure}

\subsection{Funzionamento generale del modulo a Kernel Space}

In \figurename~\ref{fig:flow} viene illustrato il funzionamento del modulo a kernel space.
Nelle successive sezioni verranno descritti i blocchi principali.

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{img5.png}
\caption{Diagramma di Flusso delle operazioni a Kernel Space}
\label{fig:flow}
\end{center}
\end{figure}

\subsection{Formato OpenBSM vs Formato Binario}

Il formato OpenBSM \'e il modo in cui le informazioni vengono rappresentate mediante
la suddivisione in record e token. Tuttavia il formato OpenBSM opera un logging di tipo binario.
La traduzione da \textit{plain text} a formato binario viene eseguita attraverso delle funzioni
che svolgono una codifica in big endian. Di seguito vengono proposte le macro che wrappano le 
funzioni che operano la trasformazione in big endian, quindi in formato binario.

\begin{lstlisting}
#define	ADD_U_CHAR(loc, val)			\
	do {					\
		*(loc) = (val);			\
		(loc) += sizeof(u_char);	\
	} while(0)


#define	ADD_U_INT16(loc, val)			\
	do {					\
		be16enc((loc), (val));		\
		(loc) += sizeof(u_int16_t);	\
	} while(0)

#define	ADD_U_INT32(loc, val)			\
	do {					\
		be32enc((loc), (val));		\
		(loc) += sizeof(u_int32_t);	\
	} while(0)

#define	ADD_U_INT64(loc, val)			\
	do {					\
		be64enc((loc), (val));		\
		(loc) += sizeof(u_int64_t); 	\
	} while(0)

#define	ADD_MEM(loc, data, size)		\
	do {					\
		memcpy((loc), (data), (size));	\
		(loc) += size;			\
	} while(0)
#define	ADD_STRING(loc, data, size)		\
	ADD_MEM(loc, data, size)
\end{lstlisting}

Le funzioni che operano l'\textit{encoding} in big endian sono le seguenti:

\begin{lstlisting}
static inline void be16enc(void *pp, uint16_t u)
{
       unsigned char *p = (unsigned char *)pp;
       
       p[0] = (u >> 8) & 0xff;
       p[1] = u & 0xff;
}

static inline void be32enc(void *pp, uint32_t u)
{
       unsigned char *p = (unsigned char *)pp;
       
       p[0] = (u >> 24) & 0xff;
       p[1] = (u >> 16) & 0xff;
       p[2] = (u >> 8) & 0xff;
       p[3] = u & 0xff;
}

static inline void be64enc(void *pp, uint64_t u)
{
       unsigned char *p = (unsigned char *)pp;

       be32enc(p, u >> 32);
       be32enc(p + 4,u & 0xffffffff);
}
\end{lstlisting}

\subsection{Scrittura di un record OpenBSM}

In \figurename~\ref{fig:flowr} sono mostrate le chiamate a funzione che hanno come scopo 
la scrittura di un record OpenBSM. Sono tutte implementate nel file \textit{test\_bsm.c}.

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{img6.png}
\caption{Diagramma di Flusso delle chiamate a funzioni per costruire un record OpenBSM}
\label{fig:flowr}
\end{center}
\end{figure}

Di seguito verranno analizzate le singole funzioni per la costruzione di un record OpenBSM.\\
La struttura risulta essere uniforme, vi \'e sempre una chiamata a GET\_TOKEN\_AREA() per
l'allocazione dell'area di memoria in base al numero e al tipo di dati da scrivere seguita
da una sequenza di wrapper il cui compito \'e quello di gestire la codifica del dato
in formato big endian e di aggiornare il puntatore alla successiva locazione libera.

\begin{itemize}
\item \textit{au\_to\_header32\_tm()}, ha il compito di scrivere l'header del record OpenBSM
con le seguenti informazioni:

	\begin{itemize}
	\item \textit{rec\_size} \'e la lunghezza dell'intero record OpenBSM
	\item AUDIT\_HEADER\_VERSION\_OPENBSM indica la versione del sistema di auditing in uso
	\item \textit{e\_type} e \textit{e\_mod} indicano il tipo di evento che \'e stato loggato
	\item in coda vengono aggiunte le informazioni relative all'ora e al tempo di esecuzione
	di quel determinato evento
	\end{itemize}

\begin{lstlisting}
struct au_token *au_to_header32_tm(int rec_size, 
	au_event_t e_type, au_emod_t e_mod, 
			struct timeval tm)
{
	struct au_token *t;
	u_char *dptr = NULL;
	u_int32_t timems;

	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 
	sizeof(u_int32_t) + sizeof(u_char) + 2 * 
	sizeof(u_int16_t) + 2 * sizeof(u_int32_t));

	ADD_U_CHAR(dptr, AUT_HEADER32);
	ADD_U_INT32(dptr, rec_size);
	ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
	ADD_U_INT16(dptr, e_type);
	ADD_U_INT16(dptr, e_mod);

	timems = tm.tv_usec/1000;
	ADD_U_INT32(dptr, tm.tv_sec);
	ADD_U_INT32(dptr, timems);
	return t;
}
\end{lstlisting}

\item \textit{au\_to\_subject32()}, ha il compito di scrivere le informazioni base del processo
su cui si sta facendo auditing quali:
	\begin{itemize}
	\item \textit{auid}, l'identificativo del processo di auditing
	\item \textit{euid}, uid effettivo
	\item \textit{egid}, gid effettivo
	\item \textit{ruid}, uid reale
	\item \textit{rgid}, gid reale
	\item \textit{pid}, pid del processo
	\item \textit{sessionid}, identificativo della sessione
	\item \textit{tid}, struttura dati che identifica porta e indirizzo nel caso di processi eseguiti 
da remoto
	\end{itemize}

\begin{lstlisting}
struct au_token *au_to_subject32(uid_t auid, uid_t euid, 
	gid_t egid, uid_t ruid,	gid_t rgid, pid_t pid, 
		unsigned int sessionid, au_tid_t *tid)
{
	struct au_token *t;
	u_char *dptr = NULL;

	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 
			9 * sizeof(u_int32_t));

	ADD_U_CHAR(dptr, AUT_SUBJECT32);
	ADD_U_INT32(dptr, auid);
	ADD_U_INT32(dptr, euid);
	ADD_U_INT32(dptr, egid);
	ADD_U_INT32(dptr, ruid);
	ADD_U_INT32(dptr, rgid);
	ADD_U_INT32(dptr, pid);
	ADD_U_INT32(dptr, sessionid);
	ADD_U_INT32(dptr, tid->port);
	ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
	return t;
}
\end{lstlisting}

\item \textit{au\_to\_return32()}, scrive il valore di ritorno dell'evento loggato e lo 
stato:
	\begin{itemize}
	\item \textit{status}, successo o insuccesso
	\item \textit{ret}, valore di ritorno della system call
	\end{itemize}

\begin{lstlisting}
struct au_token *au_to_return32(char status,u_int32_t ret)
{
	struct au_token *t;
	u_char *dptr = NULL;

	GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + 
		sizeof(u_int32_t));

	ADD_U_CHAR(dptr, AUT_RETURN32);
	ADD_U_CHAR(dptr, status);
	ADD_U_INT32(dptr, ret);
	return t;
}
\end{lstlisting}

\item \textit{au\_to\_trailer()}, scrive la dimensione totale del record OpenBSM
\begin{lstlisting}
struct au_token *au_to_trailer(int rec_size)
{
	struct au_token *t;
	u_char *dptr = NULL;
	u_int16_t magic = TRAILER_PAD_MAGIC;

	GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 
	sizeof(u_int16_t) + sizeof(u_int32_t));

	ADD_U_CHAR(dptr, AUT_TRAILER);
	ADD_U_INT16(dptr, magic);
	ADD_U_INT32(dptr, rec_size);
	return t;
}
\end{lstlisting}

In testa a tutti i token viene sempre posto un valore definito tramite una macro utile
al fine di controllo di errore. L'applicazione in user space ha infatti il compito di
effettuare un test di integrit\'a sui singoli token OpenBSM prima di processarli e la
mancata rilevazione di una di queste macro in testa al token porta a scartare l'intero
record OpenBSM.

\end{itemize}

Di seguito verranno illustrate le funzioni adibite alla gestione dei token e dei record, 
quindi all'implementazione della lista e dei wrapper. 

\begin{itemize} 
\item \textit{kau\_open()}, il suo compito \'e quello di allocare un'istanza di un record
OpenBSM e di settare i campi della struttura:
	\begin{itemize}
	\item \textit{data} viene settato a NULL 
	\item \textit{token\_q} viene inizializzato come testa della lista di \textit{au\_token}
	\item \textit{len} settata a zero in quanto non sono ancora stati inseriti dati
	\item \textit{used} settato a uno in quanto l'istanza \'e in uso
	\end{itemize}

\begin{lstlisting}
static struct au_record *kau_open(void)
{
	struct au_record *rec;
	struct au_token *t_list;

	rec = kmalloc(sizeof(*rec), GFP_KERNEL);
	rec->data = NULL;
	t_list = &(rec->token_q);
	INIT_LIST_HEAD(&(t_list->list));
	rec->len = 0;
	rec->used = 1;
	return rec;
}
\end{lstlisting}

\item \textit{kau\_write()} viene chiamata tutte le volte che bisogna aggiungere un'istanza di 
\textit{au\_token} alla lista di token in \textit{au\_record}. Viene inoltre aggiornato il valore
di \textit{rec->len} sommando la lunghezza del token appena aggiunto.
\begin{lstlisting}
static void kau_write(struct au_record *rec, 
	struct au_token *tok)
{
	struct au_token *t_list;

	t_list = &(rec->token_q);
	list_add_tail(&(tok->list), &(t_list->list));
	rec->len += tok->len;
}
\end{lstlisting}

\item \textit{kau\_close()} ha le seguenti funzionalit\'a:
	\begin{itemize}
	\item viene chiamato una sola volta al termine dell'attivit\'a di logging
	di un determinato evento 
	\item fa puntare \textit{rec->data} ad un area di memoria di demensioni
	pari al'intero record comprensivo di \textit{header} e \textit{trailer}
	\item costruisce \textit{header} e \textit{trailer} facendo le dovute 
	chiamate a funzione e le aggiunge rispettivamente in testa e in coda
	alla lista di \textit{au\_token} gestiti dall'istanza di \textit{au\_record}
	\item dealloca i singoli elementi della lista e li serializza all'intero
	dell'area di memoria puntata da \textit{rec->data}
	\end{itemize}
 
\begin{lstlisting}
static void kau_close(struct au_record *rec, 
		struct timespec *ctime, short event)
{
	u_char *dptr;
	struct list_head *pos, *q;
	size_t tot_rec_size;
	struct au_token *t, *t_list, *trail, *hdr;
 	struct timeval tm;

	tot_rec_size = rec->len + AUDIT_HEADER_SIZE + 
			AUDIT_TRAILER_SIZE;
	printk(KERN_ALERT "tot_rec_size: %d\n", 
			tot_rec_size);
	rec->data = kmalloc(tot_rec_size, GFP_KERNEL); 
	
	tm.tv_usec = ctime->tv_nsec / 1000;
	tm.tv_sec = ctime->tv_sec;
	hdr=au_to_header32_tm(tot_rec_size, event, 0, tm);
	trail = au_to_trailer(tot_rec_size);
	
	/* serialize the au_token list into rec->data */
	dptr = rec->data;
	t_list = &(rec->token_q);
	/* adding the header token to the list */
	list_add(&(hdr->list), &(t_list->list));
	/* adding the trailer token to the list */
	list_add_tail(&(trail->list), &(t_list->list));
	
	list_for_each_safe(pos, q, &(t_list->list))
	{
		t =list_entry(pos, struct au_token, list);
		memcpy(dptr, t->t_data, t->len);
		dptr += t->len;
		list_del(pos);
		kfree(t);
	}
}
\end{lstlisting}

\end{itemize}

\subsection{Preparazione del Pacchetto Netlink}

Come descritto in \figurename~\ref{fig:flow} a seguito della scrittura del record OpenBSM
\'e necessario incapsulare questa informazione nel payload di un pacchetto netlink. Sono
stati rispettati tutti i vincoli del sottosistema linux-audit sia in fatto di strutture dati
sia in fatto di protocollo di comunicazione. Per realizzare ci\'o sono state scritte le 
seguenti funzioni:

\begin{itemize}
\item \textit{audit\_buffer\_alloc()}, con le seguenti funzionalit\'a:
	\begin{itemize}
	\item inizializzare un'istanza di \textit{audit\_buffer}
	\item allocare memoria per la socket buffer delle dimensioni del record OpenBSM
	scritto precedentemente
	\item castare la socket buffer al protocollo netlink e riempire l'header
	\end{itemize}

\begin{lstlisting}
struct audit_buffer *audit_buffer_alloc(int len, 
					gfp_t gfp_mask)
{
	struct audit_buffer *ab_bsm = NULL;
	struct nlmsghdr *nlh;

	ab_bsm = kmalloc(sizeof(*ab_bsm), gfp_mask);
	if (!ab_bsm)
		goto error;
	ab_bsm->skb = alloc_skb(len, gfp_mask);
	if (!ab_bsm->skb)
		goto error;
	ab_bsm->gfp_mask = gfp_mask;
	nlh = (struct nlmsghdr *)skb_put(ab_bsm->skb, 
					NLMSG_SPACE(0));
	nlh->nlmsg_flags = 0;
	nlh->nlmsg_pid = 0;
	nlh->nlmsg_seq = 0;
	return ab_bsm;
	error:
		kfree(ab_bsm);
		return NULL;
}
\end{lstlisting}

\item \textit{audit\_log\_format\_bsm()}, il suo compito \'e quello di copiare il record
OpenBSM all'interno della socket buffer come visto in Sezione~\ref{sec:skb}
\begin{lstlisting}
void audit_log_format_bsm(struct audit_buffer *ab_bsm, 
				struct au_record *rec)
{
	int avail;
	struct sk_buff *skb;

	if(!ab_bsm)
		return;
	
	skb = ab_bsm->skb;
	avail = skb_tailroom(skb);
	
	if (avail >= rec->len)
	{
	       /* we have to copy rec->data to skb for 
	        * sending serialized tokens to userspace
	        */
		memcpy(skb_tail_pointer(skb), rec->data, 
			rec->len + AUDIT_HEADER_SIZE + 
				AUDIT_TRAILER_SIZE);
		skb_put(skb, rec->len + AUDIT_HEADER_SIZE 
				+ AUDIT_TRAILER_SIZE);
	}
}
\end{lstlisting}

\end{itemize}

\subsection{Invio del pacchetto Netlink}

A valle della creazione del record OpenBSM bisogna inviarlo a user space tramite il protocollo
netlink. L'insieme delle funzioni esposte nel capitolo precedente \'e stato combinato al fine
di ottenere il risultato voluto. \\
Da notare il passaggio di argomenti ad un thread come esposto in \textit{bsm\_test\_init()} e
\textit{ksend\_thread()}. 

\begin{itemize}
\item la chiamata a funzione \textit{kthread\_run()} ha come secondo argomento il puntato alla
struttura dati da passare al thread
\item \textit{ksend\_thread()} accetta come argometo un puntatore a \textit{void} pertanto 
l'operazione di cast viene effettuato all'interno della funzione stessa 
\item dopo aver gestito le operazioni di \textit{locking} del processo viene chiamata la funzione
\textit{netlink\_send()} per spedire il record OpenBSM wrappato all'interno dell'istanza 
della struttura \textit{audit\_buffer}.
\item \textit{netlink\_send()} ha il compito di aggiustare l'header del messaggio netlink inserendo
la lunghezza del payload quindi di spedirlo in unicast verso il PID del processo in user space
\end{itemize}

\begin{lstlisting}
static struct task_struct *ksend_task;
static DECLARE_WAIT_QUEUE_HEAD(ksend_wait);

static int __init bsm_test_init(void)
{
 	...
	ksend_task =kthread_run(ksend_thread, ab_bsm, "ksend");
	...
}
\end{lstlisting}

\begin{lstlisting}
static int ksend_thread(void *arg)
{
	struct audit_buffer *ab_bsm = 
				(struct audit_buffer *)arg;

	DECLARE_WAITQUEUE(wait, current);
	set_current_state(TASK_INTERRUPTIBLE);
	add_wait_queue(&ksend_wait, &wait);
	if(!nlk_pid)
	{
		schedule();
	}
	__set_current_state(TASK_RUNNING);
	remove_wait_queue(&ksend_wait, &wait);
	netlink_send(ab_bsm);
	return 0;
}
\end{lstlisting}

\begin{lstlisting}
void netlink_receive(struct sk_buff *skb)
{
	struct nlmsghdr *nlh;
	
	nlh = (struct nlmsghdr *)skb->data;
	printk(KERN_ALERT "%s\n", (char *)NLMSG_DATA(nlh));
	nlk_pid = NETLINK_CB(skb).pid;
	printk(KERN_ALERT "nlk_pid: %d\n", nlk_pid);
	wake_up_interruptible(&ksend_wait);
}
\end{lstlisting}

\begin{lstlisting}
void netlink_send(struct audit_buffer *ab_bsm)
{
	struct sk_buff *skb = ab_bsm->skb;
	struct nlmsghdr *nlh = nlmsg_hdr(skb);

	nlh->nlmsg_len = skb->len - NLMSG_SPACE(0);
	netlink_unicast(nl_sk, skb, nlk_pid, 0);
}
\end{lstlisting}

\section{Implementazione a User Space}

L'implementazione del processo a user space \'e molto simile a quanto visto in
Sezione~\ref{sec:netlink}. Tuttavia il payload in arrivo deve essere manipolato
al fine di scrivere in un file il record OpenBSM. Lo scopo \'e quello di permettere
un'integrazione con i tool di TrustedBSD come vedremo nel seguito. \\
Essendo il dato ricevuto in formato binario \'e stato necessario utilizzare la 
funzione \textit{fwrite()} della libreria standard del C che permette di scrivere
blocchi di dati \textit{raw}. 

\begin{itemize}
\item la funzione \textit{recvfrom()} riceve il pacchetto netlink e lo pone in 
un'area di memoria puntata da \textit{buf} definito come puntatore a char, il valore
di ritorno \textit{len} \'e la lunghezza del dato ricevuto
\item il blocco di memoria viene castato a una struttura di tipo \textit{nlmsghdr} 
\item viene creato il \textit{file pointer} associato al file aperto in scrittura
di nome \textit{bsm\_trail.bsm} 
\item tramite la funzione \textit{fwrite()} si scrive il payload del messaggio netlink
cio\'e il record OpenBSM nel file a blocchi di \textit{char} per un numero pari alla
lunghezza del messaggio ricevuto
\end{itemize}

\begin{lstlisting}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>

#define MAX_PAYLOAD 1024

int main()
{
	int sock_fd, len;
	FILE *fp;
	struct sockaddr_nl dest_addr, src_addr;
	struct nlmsghdr *nlh;
	char buf[MAX_PAYLOAD];
	socklen_t addrsize = sizeof(src_addr);

	sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_UNUSED);
	memset(&dest_addr, 0, sizeof(dest_addr));
	memset(&src_addr, 0, sizeof(src_addr));

	/*filling the destination address*/
	dest_addr.nl_family = AF_NETLINK;
	dest_addr.nl_pid = 0; //destination is kernel space
	dest_addr.nl_groups = 0; //unicast
	
	/*filling the header*/
	nlh = (struct nlmsghdr *)
			malloc(NLMSG_SPACE(MAX_PAYLOAD));
	nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
	nlh->nlmsg_pid = getpid(); //userspace app pid
	nlh->nlmsg_flags = 0;
	/*copying the message data*/
	strcpy(NLMSG_DATA(nlh), "Hello world");

	/*sending nlh through netlink socket*/
	sendto(sock_fd, nlh, nlh->nlmsg_len, 0, 
		(struct sockaddr *)&dest_addr, 
			sizeof(dest_addr));
	
	/*receiving nlh through netlink socket*/
	len = recvfrom(sock_fd, buf, MAX_PAYLOAD, MSG_DONTWAIT, 
		(struct sockaddr *)&src_addr, &addrsize);
	printf("len: %d\n%s\n", len, strerror(errno));
	nlh = (struct nlmsghdr *)buf;
	fp = fopen("bsm_trail.bsm", "w+");
	fwrite(NLMSG_DATA(nlh), sizeof(u_char), len, fp);
	close(fp);
}
\end{lstlisting}

\section{Funzionamento e Test Finale}

\begin{figure}
\begin{center}
\includegraphics[scale=.6]{img7.png}
\caption{Diagramma di flusso dell'intero progetto}
\label{fig:flowall}
\end{center}
\end{figure}

L'esecuzione del modulo a kernel space e del processo a user space portano
alla generazione di un file di nome \textit{bsm\_trail.bsm} il cui contenuto
\'e il seguente:

\begin{lstlisting}
00000000  14 00 00 00 44 0a 00 03  00 00 48 b6 73 0a 00 00  
					|....D.....H.s...|
00000010  00 28 24 00 00 00 0a 00  00 00 00 00 00 00 01 00  
					|.($.............|
00000020  00 00 02 00 00 00 03 00  00 00 04 00 00 00 05 00  
					|................|
00000030  00 00 00 00 00 00 00 27  30 00 00 00 01 13 b1 05  
					|.......'0.......|
00000040  00 00 00 44 70 c6 e5 b7  00 00 00 00 60 b6 f2 b7  
					|...Dp.......`...|
00000050  00 00 00 00                                       
						    |....|
00000054
\end{lstlisting}

A questo punto \'e stato possibile utilizzare \textbf{praudit} per convertire
il record OpenBSM in un formato \textit{human readable}:

\begin{lstlisting}
devel ver3 # ../openbsm-1.0/bin/praudit/praudit bsm_trail.bsm

header,68,10,3,0,Thu Aug 28 11:42:34 2008, + 40 msec
subject,uucp,root,bin,daemon,sys,4,5,0,0.0.0.0
return,failure : Link number out of range,1
trailer,68

devel ver3 #
\end{lstlisting}

In \figurename~\ref{fig:flowall} \'e mostrato l'intero flusso di esecuzione del progetto

\chapter{Conclusioni}

\section{Sviluppi Futuri}

\backmatter
\pagestyle{plain}

% Bibliography
\bibliographystyle{authordate4}
\bibliography{main}

\end{document}
